//
//  StateFlow.swift
//  DYSwiftFramework
//
//  Created by 黄德玉 on 2018/8/8.
//  Copyright © 2018年 none. All rights reserved.
//

// 这边根据ReSwift 和 Redux 实现最简单的数据流管理
// ReSwift 总感觉代码耦合度太高,像是直接实现一个delegate 来进行数据流管理，没啥特别高级的东西、

// 高级东西：中间件和异步的实现

/// 定义状态等级
///
/// - System: 系统状态等级最低，提供tag用来标识系统状态内部的等级,其中System是应用最高级的状态,tag = 0 是最高级状态
/// - User: 用户状态
/// - Page: 页面状态
public enum StateLevel {
    case System(tag:Int)
    case User(tag:Int)
    case Page(tag:Int)
}

/// 所有的定义的state必须符合这个空协议，State是Model，符合协议的State 必须是Struct，这个需要强制要求
public protocol State{
    var level:StateLevel { get set }
}

// 默认state:空结构体,
// 我们可以创建多个state，包含系统应用状态（定位，通知，网络连接,相机相册权限，升级提醒），
// 用户状态,
// 单页面状态,
// 弹窗管理,
//(新增)如果同时触发多个状态，需要提供状态权限流

public struct InitializedState : State{
    public var level: StateLevel = .System(tag: 0)
}

/// action 是普通的对象,用来描述state的状态，符合协议的Action最好是struct
public protocol Action{
    var type:String{ get set } // 表示将要执行的动作
    var index:Int{ get set}    // 表示完成的任务的动作序列号，可以作为数据的引用标识，唯一ID
}
public struct BaseAction:Action{
    public var type: String
    public var index: Int
    public var filter:Any?     //用于更新state的变量
}

/// Reducer 是纯函数 TODO : 这两个参数最好调过来
public typealias Reducer = (_ action:Action, _ state:State?)-> State

// 需要一个创建action的方法，action内部持有要更新的状态


/// Redux 为Store定义的原则是 ：
// 1:维持应用的state
// 2. 提供getState()
// 3. 提供dispatch(Action)
// 4. 通过subscribe(listener) 注册监听器
// 5. 通过unsubscribe(listener)

public class Store{
    
    private var currentState:State?             // 当前状态
    private var currentReducer:Reducer?    // 当前的改变状态的函数
    private var currentListeners:[()->Void] = [] // 可以实现多个订阅
    
    /// 根据state和reducer获取一个Store
    ///
    /// - Parameters:
    ///   - state: state
    ///   - reducer: reducer
    /// - Returns: Store
    public class func createStore(state:State, reducer:@escaping Reducer)->Store{
        let aStore = Store()
        aStore.currentState = state             // state 是结构体才能实现直接拷贝赋值
        aStore.currentReducer = reducer
        return aStore
    }
    
    
    /// 获取当前state
    ///
    /// - Returns: state
    public func getState()->State?{
        return currentState
    }
    
    /// 派发一个action
    ///
    /// - Parameter action: 当前action
    public func dispatch(action:Action){
        currentState = currentReducer!(action,currentState)
        currentListeners.forEach { (value) in
            value()
        }
    }
    
    public func subscribe(listener:@escaping ()->Void){
        currentListeners.append(listener)
    }
    
    public func unsubscribe(){
        currentListeners = []
    }
}








